

import Product;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class ExcelWriterTest {
    public static void main(String[] args) throws IOException, IllegalAccessException {
        ExcelWriter exr = new ExcelWriter("C:/Users/Administrator/Desktop/template.xlsx");

        /*----------------${*} marker替换示例----------------*/
        // 替换所有sheet中${year}、${quarter}、${deptName}、${recordUser}
        HashMap<String, Object> baseInfoMap = new HashMap<>();
        baseInfoMap.put("year", 2021);
        baseInfoMap.put("quarter", 3);
        baseInfoMap.put("deptName", "产品库存管理部");
        baseInfoMap.put("recordUser", "搬砖工人");
        // 替换excel中所有sheet中的模板
        exr.replaceMarker(baseInfoMap);

        String title1 = "AAA";
        String title2 = "BBB";
        String title3 = "CCC";
        baseInfoMap.put("title1", title1);
        baseInfoMap.put("title2", title2);
        baseInfoMap.put("title3", title3);
        // 可每个属性单独替换
        exr.replaceMarker(baseInfoMap);

        // sheet重命名
        exr.renameSheetTitle("title1", title1);
        exr.renameSheetTitle("title2", title2);
        exr.renameSheetTitle("title3", title3);

        // 初始化参数。
        List<Product> productList = initData();

        /*----------------sheet1 模板简单使用----------------*/
        exr.setMarkersByRow(title1, productList, "product");


        /*----------------sheet2 marker替换（按行追加数据）与公式计算----------------*/
        /**
         * 申明：ExcelWriter.setMarkersByRow及其重载方法，不支持跨行合并单元格处理。见ExcelWriter.copyRowMerge方法fixme部分。
         * 所以，我们约定：
         * 1、约定每个category对应的品牌个数为5个，且模板中需要把5列创建好，可以多余5列，但是不能少于。
         * 2、每个category下对应的品牌个数不一致的话，公式计算时可能会有问题。
         * 3、合并单元格问题，可根据工具类ExcelWriter.copyRowMerge方法中fixme部分，再结合业务进行修改
         * 4、公式计算问题，求平均或者合计的行或列，可根据模板调整行或列的下移后者右移，见ExcelWriter.setRowMarkersByCol；ExcelWriter.setRowMarkersByRow方法中fixme部分
         */
        // 按大类分组。key：大类名称，value：对应集合，size=5
        Map<String, List<Product>> categoryMap = productList.stream().collect(Collectors.groupingBy(Product::getCategory));
        for (int i = 1; i <= categoryMap.keySet().size(); i++) {
            String category = String.valueOf(categoryMap.keySet().toArray()[i-1]);
            baseInfoMap.put("category"+i, category);
            exr.replaceMarker(baseInfoMap);

            List<Product> products = categoryMap.get(category);
            // 按行替换marker
            exr.setMarkersByRow(title2, products, "category"+i);
        }
        // 设置sheet中所有合计值。
        List<Integer[]> contentAllLocation = exr.getContentAllLocation(title2, "合计");
        for (Integer[] location : contentAllLocation) {
            int rowIdx = location[0];
            int colIdx = location[3]+1;
            exr.computeFormula(title2, "SUM", false, rowIdx, colIdx,
                    rowIdx-5, rowIdx-1, colIdx, colIdx);
        }

        /*----------------sheet3 marker替换（按列追加数据）----------------*/
        /**
         * 申明：ExcelWriter.setMarkersByCol及其重载方法，不支持跨行合并单元格处理。见ExcelWriter.copyRowMerge方法fixme部分。
         * 所以，我们约定：
         * 1、约定每个category对应的品牌个数为5个，且模板中需要把5列创建好，可以多余5列，但是不能少于。
         * 2、每个category下对应的品牌个数不一致的话，公式计算时可能会有问题。
         * 3、合并单元格问题，可根据工具类ExcelWriter.copyRowMerge方法中fixme部分，再结合业务进行修改
         * 4、公式计算问题，求平均或者合计的行或列，可根据模板调整行或列的下移后者右移，见ExcelWriter.setRowMarkersByCol；ExcelWriter.setRowMarkersByRow方法中fixme部分
         */
        for (int i = 1; i <= categoryMap.keySet().size(); i++) {
            String category = String.valueOf(categoryMap.keySet().toArray()[i-1]);

            // 外层List代表有几列数据，内层List代表当前列数据有几行值
            List<List<Object>> brandWrapList = new ArrayList<>();
            List<List<Object>> descWrapList = new ArrayList<>();
            List<Product> products = categoryMap.get(category);
            for (Product product : products) {
                brandWrapList.add(Arrays.asList(product.getBrand(), product.getBrand()));// 添加2个重复元素，体现是逐行添加数据
                descWrapList.add(Arrays.asList(product.getDesc(), product.getDesc()));// 添加2个重复元素，体现是逐行添加数据
            }
            // 设置品牌
            exr.setMarkersByCol(title3, brandWrapList, "${category" + i + ".brand}");
            // 设置描述
            exr.setMarkersByCol(title3, descWrapList, "${category" + i + ".desc}");
            // todo：设置平均分和合计
        }


        byte[] bt = exr.getBytes();
        exr.coverWriteToLocal("C:\\Users\\Administrator\\Desktop", "记录表.xlsx", bt);
        exr.close();
    }

    public static List<Product> initData(){
        return Arrays.asList(
                new Product(1, 10, "20200101", "电子产品类", "OPPO", "说明：拍照5分钟，充电两小时", 2000.22d, LocalDateTime.now()),
                new Product(2, 20, "20200101", "电子产品类", "VIVO", "说明：x60", 1111.22d, LocalDateTime.now()),
                new Product(3, 30, "20200101", "电子产品类", "小米", "说明：为发烧而生", 3333.22d, LocalDateTime.now()),
                new Product(4, 40, "20200101", "电子产品类", "华为", "说明：鸿蒙操作系统", 4444.22d, LocalDateTime.now()),
                new Product(5, 50, "20200101", "电子产品类", "苹果", "说明：一起都是产品问题", 5555.22d, LocalDateTime.now()),

                new Product(6, 60, "20200101", "家居类", "桌子", "说明：这是桌子", 17.22d, LocalDateTime.now()),
                new Product(7, 70, "20200101", "家居类", "椅子", "说明：这是椅子", 21.22d, LocalDateTime.now()),
                new Product(8, 80, "20200101", "家居类", "油烟机", "说明：这是油烟机", 34.22d, LocalDateTime.now()),
                new Product(9, 90, "20200101", "家居类", "电风扇", "说明：这是电风扇", 56.22d, LocalDateTime.now()),
                new Product(10, 100, "20200101", "家居类", "液晶电视", "说明：这是液晶电视", 32.22d, LocalDateTime.now())
        );
    }
}
